// Base on OpenGL Tutorial 4 by Fotis Liarokapis
//Edited and further developed by Florin N. Coada
#include "main.h"
#include "Planets.h"
int showMenu=1;
int cameraType=1;

// Spin the scene function 1, stop the planets from spining
void spinScene1(void)
{
glutPostRedisplay();
}

//Spin the scene function 2, make the planets spin
void spinScene2(void)
{
//call the spin functions and redraw 
spinSun();
spinPlanets();
glutPostRedisplay();
}
// Draw function
void draw(void)
{
// Clears the color buffer bit and depth buffer bit
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Push the current matrix stack
glPushMatrix();
//Show the menu
if(showMenu){
gluLookAt(1.707754,0.375094,-0.445263, 
          1.707754-0.744643,0.375094,-0.445263-0.031451,
		  0.0, 1.0, 0.0);

glutIdleFunc(spinScene2);
mainMenu();
drawSun();
orientMeY(angleX,angleY);
}

//Show the solar system
if(showMenu==0){
if(cameraType==2) setCamera2();
else setCamera1();
drawSun();
drawPlanets();
drawAsteroids();
// Pops the current matrix stack
glPopMatrix();
}
// Swaps the buffers
glutSwapBuffers();
}
// Initialise function
void initialise()
{
// Clears the color pixels to white
glClearColor(0.0, 0.0, 0.0, 0.0);
// Selects smooth shading
glShadeModel(GL_SMOOTH);
// Enable lighting operations
glEnable(GL_LIGHTING);
// Enable an OpenGL light
glEnable(GL_LIGHT0);
// Enable depth test
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
//initialize sun texture
initSun();
//initialize planet texture
initPlanetsTex();
}
// Reshapes the window
void reshape(int w, int h)
{
// Sets the viewport
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
// Applies matrix operations to the projection matrix stack
glMatrixMode(GL_PROJECTION);
// Replaces the current matrix with the identity matrix
glLoadIdentity();
// Sets up a perspective projection matrix
gluPerspective(40.0, (GLfloat) w/(GLfloat) h, 0.01, 200.0);
// Applies matrix operations to the modelview matrix stack
glMatrixMode(GL_MODELVIEW);
// Replaces the current matrix with the identity matrix
glLoadIdentity();
}
// Function that reads input from the keyboard
void Keyboard(unsigned char key, int A, int B)
{
if(cameraType==2) switch(key)
{
// Start rotation
case '1': glutIdleFunc(spinScene2); // Sets the global idle callback
break;
// Stop rotation
case '2': glutIdleFunc(spinScene1); // Sets the global idle callback
break;
//Camera 2
case 'a':
	moveLeft();break;// go left on the circle
case 'd':
	moveRight();break; // go right on the circle
case 's':
	moveUp(-0.1);break; // move up
case 'w':
	moveUp(0.1);break; // move down
case 'q':
	zoom(-0.1);break; //zoom in
case 'e':
	zoom(0.1);break; //zoom out
case '#':
	cameraType=1;
	break; // change the camera type
case 'o':    //increase orbiting speed
	updateSpeed(-0.01);break;
case 'p':   //decrease orbiting speed
	updateSpeed(0.01);break;
case 27: 
	exit(0); // Terminates the program
	break;

}
else switch(key)
{
// Start rotation
case '1': glutIdleFunc(spinScene2); // Sets the global idle callback
break;
// Stop rotation
case '2': glutIdleFunc(spinScene1); // Sets the global idle callback
break;
//Camera 1
case 's' :    //look down
	angleY -= 0.03;
	orientMeY(angleX,angleY);break;
case 'w' :   //look  up
	angleY +=0.03;
	orientMeY(angleX,angleY);break;
case 'a' : 
	angleX -= 0.03;  //look left
	orientMeX(angleX,angleY);break;
case 'd' :
	angleX += 0.03; //look right
	orientMeX(angleX,angleY);break;
case 'q':    //move forward
	moveMeFlat(1);break;
case 'e':    //move backward
	moveMeFlat(-1);break;
case 'o':    //increase orbiting speed
	updateSpeed(-0.01);break;
case 'p':   //decrease orbiting speed
	updateSpeed(0.01);break;
case 32:    //start rendering the solar system
	if(showMenu){
	showMenu=0;
	moveMeFlat(1);
	PlaySound("soundtrack.wav",NULL,SND_FILENAME|SND_LOOP|SND_ASYNC);
	}
	break;
case '#':
	cameraType=2;
	break;
// Escapes from the program by pressing 'Esc'
case 27: 
	exit(0); // Terminates the program
	break;
default:
break;
}
}
// Function that creates a menu used from a mouse
void mouseMenu(int value)
{
if(showMenu==0){
if(value == 1)
glutIdleFunc(spinScene1);
if(value == 2)
glutIdleFunc(spinScene2);
if(value == 3)
updateSpeed(0.05);
if(value == 4)
updateSpeed(-0.05);
if(value == 5)
	if(cameraType==1) cameraType=2;
	else cameraType=1;
if(value == 6)
	exit(0);
}
}
// Function that prints a menu on the command window
void menuIn()
{
// Create a widget menu
glutCreateMenu(mouseMenu);
// Add a menu entry
glutAddMenuEntry("Stop Rotation", 1);
// Add a menu entry
glutAddMenuEntry("Start Rotation", 2);
//Add a menu entry
glutAddMenuEntry("Increase Rotation Speed", 3);
//Add a menu entry
glutAddMenuEntry("Decrease Rotation Speed", 4);
//Add a menu entry
glutAddMenuEntry("Change Camera", 5);
// Add a menu entry
glutAddMenuEntry("Quit", 6);
// Attach menu to mouse right button
glutAttachMenu(GLUT_RIGHT_BUTTON);
}

// Main function
int main(int argc, char **argv)
{
printf("Loading .... Please wait for the program to load.");
//Initialize planets
initPlanets();
//Initialize asteroids
initAsteroids();
// Initialise GLUT library
glutInit(&argc, argv);
// Initialise the display mode
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
//glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
// Initialise the window position
glutInitWindowPosition(0, 0);
// Initialise the window size
glutInitWindowSize(800, 600);
// Creates a window on the screen
glutCreateWindow ("212CR Assignment One");
//Activate widget menu
menuIn();
// Call the initialise function
initialise();
// The display function is called each time there is a display callback
glutDisplayFunc(draw);
// The reshape function reshapes the scene
glutReshapeFunc(reshape);
// Function that reads input from the keyboard
glutKeyboardFunc(Keyboard);
// Causes the program to enter an event-processing loop
glutMainLoop();
return 0;
}